Skip to content

feat(rotation): Phase 3 — manual rotate UI + handlers (#72) - #130

Merged
sarg3nt merged 1 commit into
feature/issue-72-phase-2-rotation-endpointsfrom
feature/issue-72-phase-3-rotate-ui
May 17, 2026
Merged

feat(rotation): Phase 3 — manual rotate UI + handlers (#72)#130
sarg3nt merged 1 commit into
feature/issue-72-phase-2-rotation-endpointsfrom
feature/issue-72-phase-3-rotate-ui

Conversation

@sarg3nt

@sarg3nt sarg3nt commented May 17, 2026

Copy link
Copy Markdown
Owner

Summary

Stacked on #129 (Phase 2). Surfaces the rotator behind two operator-visible buttons — the bit that makes the keyring work actually usable.

Backend

  • POST /settings/boxes/{id}/rotate-key — rotates one box. Returns {success, new_kid, old_kid, retire_after} or 4xx/5xx with {success: false, message}. Constructs a rotator per request from the handler's existing DB + encryptor
  • POST /settings/boxes/rotate-key-all — iterates every enabled box. Reports per-box success/failure so the operator sees exactly which boxes need follow-up. Failures don't halt the run; operator decides whether to investigate or move on

Both routes wired into the admin-only /settings group alongside existing box CRUD. Same permission gate as HAProxyBoxUpdatePost.

UI

  • Box edit form: new "Rotate API key" section under the API Key field with a Rotate Key button. Visible only on edit. Click → showConfirmDialog (warning style explaining the 24h overlap) → POST → toast on success or alert dialog on failure
  • Boxes list: "Rotate All Keys" button next to "Add Box". Visible only when at least one box exists. Click → confirm → POST → success toast or alert with per-box failure list when partial
  • JS uses established showConfirmDialog / showAlertDialog / showToast APIs per the CLAUDE.md "never use native confirm/alert/prompt" rule

Test plan

  • Visit a box edit page → click Rotate Key → confirm dialog appears → confirm → toast shows new kid + retire timestamp
  • Visit boxes list → click Rotate All Keys → confirm → success toast OR alert with per-box failure list
  • Rotation marks old key as secondary in the keyring (verify via GET /api/v1/system/keyring)
  • All existing tests still pass; no new tests in this PR (rotator behaviour covered in feat(rotation): Phase 2 — install/use/remove endpoints + rotator (#72) #129)

Stack

Phase 3 of 5. Base: feature/issue-72-phase-2-rotation-endpoints (#129).

Closes part of #72.

🤖 Generated with Claude Code

Surfaces the Phase 2 rotator behind two operator-visible buttons —
the bit that makes the keyring work actually usable. No new
back-end abstractions; just two thin handlers that compose the
existing rotator with the dashboard's box management.

Backend
-------

`POST /settings/boxes/{id}/rotate-key`
- Rotates one box. Returns 200 with `{success, new_kid, old_kid,
  retire_after}` or 4xx/5xx with `{success: false, message}`.
- Constructs a rotator per request from the handler's existing DB +
  encryptor — no new singletons.

`POST /settings/boxes/rotate-key-all`
- Iterates every enabled box and rotates each through the same
  rotator. Reports per-box success/failure so the operator sees
  exactly which boxes need follow-up. Failures on one box don't
  halt the run; this matches the homelab use case better than a
  strict circuit-breaker — operator decides whether to investigate
  one bad box or move on.

Both routes are wired into the admin-only `/settings` group in
cmd/server/main.go alongside the existing box CRUD routes; same
permission gate as `HAProxyBoxUpdatePost` etc.

UI
--

Box edit form (`HAProxyBoxEditPage`)
- New "Rotate API key" section under the API-Key field with a Rotate
  Key button. Visible only on edit (server != nil).
- Click → `showConfirmDialog` (warning style) explaining the 24h
  overlap → POST → toast on success or alert dialog on failure.
- Reuses the in-page rotate-spinner SVG to surface in-flight state.

Boxes list (`HAProxyBoxesPageContent`)
- New "Rotate All Keys" button next to the existing "Add Box"
  button. Visible only when at least one box exists.
- Click → confirm → POST → success toast or alert dialog with a
  per-box failure list when partial.

JS uses the established `showConfirmDialog` / `showAlertDialog` /
`showToast` APIs from `layouts.Base`, per the CLAUDE.md "never use
native confirm/alert/prompt" rule.

Tests
-----

No new tests — the rotator's behaviour is already covered by
`services/agent_keyring/rotator_test.go` (Phase 2). The handlers
are thin enough that adding HTTP-level tests would duplicate the
rotator-side coverage. Browser-level testing of the new UI was not
performed in this commit; operator should smoke-test by hitting
both buttons end-to-end before merging.

Refs: Phase 3 of the implementation plan posted to #72.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sarg3nt
sarg3nt force-pushed the feature/issue-72-phase-2-rotation-endpoints branch from b606c7c to d174a75 Compare May 17, 2026 19:03
@sarg3nt
sarg3nt force-pushed the feature/issue-72-phase-3-rotate-ui branch from c66f37a to 139e7b7 Compare May 17, 2026 19:03
@sarg3nt
sarg3nt merged commit dc36728 into feature/issue-72-phase-2-rotation-endpoints May 17, 2026
3 checks passed
@sarg3nt
sarg3nt deleted the feature/issue-72-phase-3-rotate-ui branch May 17, 2026 19:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant